﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Celeriq.Graphing.Core;
using Celeriq.ManagementStudio.EventArguments;
using System.Collections;

namespace Celeriq.ManagementStudio.UserControls
{
	public partial class ServerPropertySheet : UserControl
	{
		public event EventHandler<RepositoryListEventArgs> RepositorySelected;
		public event EventHandler<RepositoryListEventArgs> RepositoryDeleted;
		public event EventHandler<MouseEventArgs> MouseUp;

		private List<RemotingObjectCache> _list = null;

		protected void OnRepositorySelected(RepositoryListEventArgs e)
		{
			if (this.RepositorySelected != null)
				this.RepositorySelected(this, e);
		}

		protected void OnRepositoryDeleted(RepositoryListEventArgs e)
		{
			if (this.RepositoryDeleted != null)
				this.RepositoryDeleted(this, e);
		}

		protected void OnMouseUp(MouseEventArgs e)
		{
			if (this.MouseUp != null)
				this.MouseUp(this, e);
		}

		public ServerPropertySheet()
		{
			InitializeComponent();

			this.Resize += new EventHandler(RepositoryPropertySheet_Resize);
			lvwItem.ItemSelectionChanged += lvwItem_ItemSelectionChanged;
			lvwItem.KeyDown += lvwItem_KeyDown;
			lvwItem.MouseUp += lvwItem_MouseUp;
			lvwItem.ListViewItemSorter = new ListViewColumnSorter(lvwItem);
			lvwItem.ColumnClick += lvwItem_ColumnClick;
			txtFilter.TextChanged += txtFilter_TextChanged;

			lvwItem.Columns.Clear();
			lvwItem.Columns.Add(new ColumnHeader() {Text = "ID", Width = 100});
			lvwItem.Columns.Add(new ColumnHeader() {Text = "Name", Width = 100});
			lvwItem.Columns.Add(new ColumnHeader() { Text = "Disk Size", Width = 100 });
			lvwItem.Columns.Add(new ColumnHeader() { Text = "Memory Size", Width = 100 });
			lvwItem.Columns.Add(new ColumnHeader() {Text = "Count", Width = 100});
			lvwItem.Columns.Add(new ColumnHeader() {Text = "Created", Width = 100});
		}

		private void txtFilter_TextChanged(object sender, EventArgs e)
		{
			Reload();
		}

		private void lvwItem_ColumnClick(object sender, ColumnClickEventArgs e)
		{
			// Determine if clicked column is already the column that is being sorted.
			var sorter = lvwItem.ListViewItemSorter as ListViewColumnSorter;
			if (e.Column == sorter.SortColumn)
			{
				// Reverse the current sort direction for this column.
				if (sorter.Order == SortOrder.Ascending)
				{
					sorter.Order = SortOrder.Descending;
				}
				else
				{
					sorter.Order = SortOrder.Ascending;
				}
			}
			else
			{
				// Set the column number that is to be sorted; default to ascending.
				sorter.SortColumn = e.Column;
				sorter.Order = SortOrder.Ascending;
			}

			// Perform the sort with these new sort options.
			lvwItem.Sort();
		}

		private void lvwItem_MouseUp(object sender, MouseEventArgs e)
		{
			this.OnMouseUp(e);
		}

		private void lvwItem_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Delete)
			{
				if (lvwItem.SelectedItems.Count > 0)
				{
					if (MessageBox.Show("Do you wish to delete the selected items?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
					{
						var dList = new List<ListViewItem>();
						foreach (ListViewItem item in lvwItem.SelectedItems)
						{
							dList.Add(item);
						}
						this.OnRepositoryDeleted(new RepositoryListEventArgs(dList.Select(x => x.Tag).Cast<RemotingObjectCache>().ToList()));
						dList.ForEach(x => lvwItem.Items.Remove(x));
					}
				}
			}
			else if (e.KeyCode == Keys.A && e.Control)
			{
				foreach (ListViewItem item in lvwItem.Items)
				{
					item.Selected = true;
				}
			}
		}

		private void lvwItem_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
		{
			if (lvwItem.SelectedItems.Count > 0)
			{
				var dList = new List<ListViewItem>();
				foreach (ListViewItem item in lvwItem.SelectedItems)
				{
					dList.Add(item);

				}
				this.OnRepositorySelected(new RepositoryListEventArgs(dList.Select(x => x.Tag).Cast<RemotingObjectCache>().ToList()));
			}
		}

		public void Populate(List<RemotingObjectCache> list)
		{
			_list = list;
			Reload();
		}

		private void Reload()
		{
			lvwItem.BeginUpdate();
			try
			{
				RemotingObjectCache selected = null;
				if (lvwItem.SelectedItems.Count > 0)
				{
					selected = lvwItem.SelectedItems[0].Tag as RemotingObjectCache;
				}

				lvwItem.Items.Clear();
				var filter = txtFilter.Text.Trim().ToLower();
				if (string.IsNullOrEmpty(filter))
				{
					foreach (var item in _list.OrderBy(x => x.Repository.Name))
						this.AddPropertyItem(item);
				}
				else
				{
					foreach (var item in _list.Where(x => x.Repository.Name.ToLower().Contains(filter) || x.Repository.ID.ToString().ToLower().Contains(filter)).OrderBy(x => x.Repository.Name))
						this.AddPropertyItem(item);
				}
				if (selected != null)
				{
					var item = ((IEnumerable) lvwItem.Items).OfType<ListViewItem>().ToList().FirstOrDefault(x => x.Tag == selected);
					if (item != null)
						item.Selected = true;
				}
			}
			catch (Exception ex)
			{
				throw;
			}
			finally
			{
				lvwItem.EndUpdate();
			}

		}

		private void AddPropertyItem(RemotingObjectCache item)
		{
			var newItem = new ListViewItem();
			newItem.Tag = item;

			//Add in reverse order
			newItem.ImageIndex = (item.IsLoaded ? 0 : 1);
			newItem.Text = item.Repository.ID.ToString();
			newItem.SubItems.Add(item.Repository.Name);
			newItem.SubItems.Add(Celeriq.ManagementStudio.Objects.Utilities.ToSizeDisplay(item.DataDiskSize));
			newItem.SubItems.Add(Celeriq.ManagementStudio.Objects.Utilities.ToSizeDisplay(item.DataMemorySize));
			newItem.SubItems.Add(item.ItemCount.ToString("###,###,###,##0"));
			var ds = "(unknown)";
			if (item.Repository.CreatedDate > DateTime.MinValue)
				ds = item.Repository.CreatedDate.ToString("yyyy-MM-dd HH:mm:ss");
			newItem.SubItems.Add(ds);

			lvwItem.Items.Add(newItem);

		}

		private void RepositoryPropertySheet_Resize(object sender, EventArgs e)
		{
			//pnlLeft.Width = this.Width / 2;
		}

		#region Column Sorter

		public class ListViewColumnSorter : IComparer
		{
			/// <summary>
			/// Specifies the column to be sorted
			/// </summary>
			private int ColumnToSort;
			/// <summary>
			/// Specifies the order in which to sort (i.e. 'Ascending').
			/// </summary>
			private SortOrder OrderOfSort;
			/// <summary>
			/// Case insensitive comparer object
			/// </summary>
			private CaseInsensitiveComparer ObjectCompare;

			private ListView _ctrl = null;

			/// <summary>
			/// Class constructor.  Initializes various elements
			/// </summary>
			public ListViewColumnSorter(ListView ctrl)
			{
				_ctrl = ctrl;

				// Initialize the column to '0'
				ColumnToSort = 0;

				// Initialize the sort order to 'none'
				OrderOfSort = SortOrder.None;

				// Initialize the CaseInsensitiveComparer object
				ObjectCompare = new CaseInsensitiveComparer();
			}

			/// <summary>
			/// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
			/// </summary>
			/// <param name="x">First object to be compared</param>
			/// <param name="y">Second object to be compared</param>
			/// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
			public int Compare(object x, object y)
			{
				int compareResult;
				ListViewItem listviewX, listviewY;

				// Cast the objects to be compared to ListViewItem objects
				listviewX = (ListViewItem)x;
				listviewY = (ListViewItem)y;

				var a = listviewX.SubItems[ColumnToSort].Text;
				var b = listviewY.SubItems[ColumnToSort].Text;
				var item1 = listviewX.Tag as RemotingObjectCache;
				var item2 = listviewY.Tag as RemotingObjectCache;

				if (this.SortColumn != -1)
				{
					if (_ctrl.Columns[this.SortColumn].Text == "Disk Size" ||
						_ctrl.Columns[this.SortColumn].Text == "Memory Size")
					{
						a = item1.DataDiskSize.ToString("0000000000");
						b = item2.DataDiskSize.ToString("0000000000");
					}
					else if (_ctrl.Columns[this.SortColumn].Text == "Count")
					{
						a = item1.ItemCount.ToString("0000000000");
						b = item2.ItemCount.ToString("0000000000");
					}
					else if (_ctrl.Columns[this.SortColumn].Text == "Created")
					{
						a = item1.Repository.CreatedDate.ToString("yyyy-MM-dd HH:mm:ss");
						b = item2.Repository.CreatedDate.ToString("yyyy-MM-dd HH:mm:ss");
					}
				}

				// Compare the two items
				compareResult = ObjectCompare.Compare(a, b);

				// Calculate correct return value based on object comparison
				if (OrderOfSort == SortOrder.Ascending)
				{
					// Ascending sort is selected, return normal result of compare operation
					return compareResult;
				}
				else if (OrderOfSort == SortOrder.Descending)
				{
					// Descending sort is selected, return negative result of compare operation
					return (-compareResult);
				}
				else
				{
					// Return '0' to indicate they are equal
					return 0;
				}
			}

			/// <summary>
			/// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
			/// </summary>
			public int SortColumn
			{
				set
				{
					ColumnToSort = value;
				}
				get
				{
					return ColumnToSort;
				}
			}

			/// <summary>
			/// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
			/// </summary>
			public SortOrder Order
			{
				set
				{
					OrderOfSort = value;
				}
				get
				{
					return OrderOfSort;
				}
			}

		}
		#endregion

	}
}